class D3Force {
    constructor(data) {
      this.chartData = data
      this.width = 500
      this.height = 500
  
      this.simulation = d3.forceSimulation()
        .force('charge_force', d3.forceManyBody().strength(-200))
        .force('center_force', d3.forceCenter(this.width / 2, this.height / 2))
        .on('tick', this._ticked.bind(this))
    }
  
    render() {
      this._createSvg()
        ._addNodes()
        ._addLinks()
        ._drawLinks()
        ._drawNodes()
    }
  
    _createSvg() {
      this.svg = d3.select('body')
        .append('svg')
        .classed('chart', true)
        .attr('width', this.width)
        .attr('height', this.height)
  
      return this
    }
  
    _addNodes() {
      this.simulation.nodes(this.chartData.nodes)
  
      return this
    }
  
    _addLinks() {
      const linkForce = d3.forceLink(this.chartData.links)
      this.simulation.force('link', linkForce)
  
      return this
    }
  
    _drawNodes() {
      const nodeGroup = this.svg.append('g')
        .classed('nodes', true)
      this.nodes = nodeGroup.selectAll('circle')
        .data(this.chartData.nodes)
        .enter()
        .append('circle')
        .classed('circle', true)
        .attr('r', 10)
  
      return this
    }
  
    _drawLinks() {
        const linkGroup = this.svg.append('g')
          .classed('links', true)
      this.links = linkGroup.selectAll('line')
          .data(this.chartData.links)
        .enter()
        .append('line')
        .classed('link', true)
    
      return this
    }
  
    _ticked() {
        this.links.attr('x1', d => d.source.x)
          .attr('y1', d => d.source.y)
        .attr('x2', d => d.target.x)
        .attr('y2', d => d.target.y)
      this.nodes.attr("cx", d => d.x)
        .attr("cy", d => d.y);
    }
  }
  
  const data = {
    nodes: [{
        name: "桂林"
      }, {
        name: "广州"
      },
      {
        name: "厦门"
      }, {
        name: "杭州"
      },
      {
        name: "上海"
      }, {
        name: "青岛"
      },
      {
        name: "天津"
      }
    ],
    links: [{
        source: 0,
        target: 1
      }, {
        source: 0,
        target: 2
      },
      {
        source: 0,
        target: 3
      }, {
        source: 1,
        target: 4
      },
      {
        source: 1,
        target: 5
      }, {
        source: 1,
        target: 6
      }
    ]
  }
  
  const force = new D3Force(data)
  force.render()
  